/*
 * @Author: 生俊甫 1758142861@qq.com
 * @Date: 2025-01-25 16:02:24
 * @LastEditors: 生俊甫 1758142861@qq.com
 * @LastEditTime: 2025-01-25 17:53:32
 * @FilePath: /sjf/weChat_project/test_to_there/framework/etcd_test/etcd.hpp
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
#include <iostream>
#include <etcd/Client.hpp>
#include <etcd/KeepAlive.hpp>
#include <etcd/Response.hpp>
#include <etcd/Watcher.hpp>
#include <thread>
#include <functional>
#include "../spdlog_test/logger.hpp"

//服务器注册客户端类
class registry
{
public:
    using ptr = std::shared_ptr<registry>;
    registry(const std::string& etcd_host)
    :_client(std::make_shared<etcd::Client>(etcd_host))
    ,_keep_alive(_client->leasekeepalive(3).get())
    ,_lease_id(_keep_alive->Lease())
    {}
    ~registry() { _keep_alive->Cancel(); }
    bool registry_t(const std::string& key,const std::string& val)
    {
        auto resp = _client->put(key,val,_lease_id).get();
        if(resp.is_ok() == false)
        {
            LOG_ERROR("新增数据失败: {}",resp.error_message());
            return false;
        }
        return true;
    }
private:
    std::shared_ptr<etcd::Client> _client; //客户端对象
    std::shared_ptr<etcd::KeepAlive> _keep_alive; //保活对象
    uint64_t _lease_id; //租约id
};
//服务器发现客户端类
class discovery
{
public:
    using ptr = std::shared_ptr<discovery>;
    using NotifyCallback = std::function<void(std::string,std::string)>;
    discovery(const std::string& host,const std::string& basedir,
                const NotifyCallback &put_cb,
                const NotifyCallback &del_cb)
    :_client(std::make_shared<etcd::Client>(host))
    ,_put_cb(put_cb),_del_cb(del_cb)
    {
        //首先进行服务的发现
        auto resp = _client->ls("/service").get();
        if (resp.is_ok() == false)
        {
            LOG_ERROR("获取键值对信息出差: {}", resp.error_message());
        }
        int sz = resp.keys().size();
        for (int i = 0; i < sz; i++)
        {
            if(put_cb) _put_cb(resp.key(i),resp.value(i).as_string());
        }
        //进行事件监控，监控数据发送改变时调用回调函数
        _watcher = std::make_shared<etcd::Watcher>(*_client.get(),basedir,
                    std::bind(&discovery::callback,this,std::placeholders::_1),true);
    }
    ~discovery()
    {}
private:
    void callback(const etcd::Response& resp)
    {
        if(resp.is_ok() == false)
        {
            LOG_ERROR("收到一个错误的事件通知: {}", resp.error_message());
            return;
        }
        for (auto const &ev : resp.events())
        {
            if (ev.event_type() == etcd::Event::EventType::PUT)
            {
                if(_put_cb) _put_cb(ev.kv().key(),ev.kv().as_string());
                LOG_DEBUG("新增服务: {}-{}",ev.kv().key(),ev.kv().as_string());
            }
            else if (ev.event_type() == etcd::Event::EventType::DELETE_)
            {
                if(_del_cb) _del_cb(ev.prev_kv().key(),ev.prev_kv().as_string());
                LOG_DEBUG("下线服务: {}-{}",ev.prev_kv().key(),ev.prev_kv().as_string());
            }
        }
    }
private:
    NotifyCallback _put_cb;
    NotifyCallback _del_cb;
    std::shared_ptr<etcd::Client> _client;
    std::shared_ptr<etcd::Watcher> _watcher;
};